package ferp.center.server.task;

import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.taskqueue.TaskHandle;
import ferp.center.server.Action;
import ferp.center.server.entity.Rating;
import ferp.center.server.ranking.Ranker;

import javax.persistence.EntityManager;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

import static com.google.appengine.api.taskqueue.TaskOptions.Builder.withUrl;

/**
 * User: igorgok
 * Date: 6/4/13 1:56 PM
 */
public class TaskRangeTreeUpdate extends HttpServlet
{
  public static void queue(Rating rating)
  {
    TaskHandle t = Ranker.queue().add(withUrl(URL).param(RID, String.valueOf(KeyFactory.keyToString(rating.getKey()))));

    Action.logger().info("queued tree update, cfg=[" + rating.getConfiguration() + "], player=[" + rating.getProfile().getName() + "], score=" + rating.getValue());
    //Action.logger().info("handle=" + t.toString());
  }

  protected void doPost(final HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
  {
    Action.execute(request, new Action.Task()
    {
      @Override
      protected void run(EntityManager em, HttpServletRequest request) throws IOException
      {
        Key key = KeyFactory.stringToKey(request.getParameter(RID));
        Rating rating = null;
        int attempt = 0;

        // always sleep for 2 seconds to ensure we do not update entities too fast
        do
        {
          try
          {
            log("going to sleep before attempt #" + attempt);

            Thread.sleep(SLEEP_TIME_MS);
          }
          catch (InterruptedException e)
          {
            log("sleep interrupted");
          }

          rating = em.find(Rating.class, key);
        }
        while (rating == null && attempt++ < MAX_LOOKUP_ATTEMPTS);

        if (rating != null)
        {
          log("updating tree [" + rating.getConfiguration() + "] with rating " + rating.getValue());

          Ranker.update(em, rating);
        }
        else
          log("could not find rating " + key);
      }
    });
  }

  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
  {
  }

  private static final String URL = Url.rt("update");
  private static final String RID = "rid";
  private static final int MAX_LOOKUP_ATTEMPTS = 15;
  private static final int SLEEP_TIME_MS = 2000;
}
